package com.ikas.ai.server.config.mysql;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.ikas.ai.server.config.MybatisObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @Description: 配置mysql数据源
 * @Author: qi.yilai
 * @Date: 2023/1/11 15:58
 * @Version: 1.0.0
 **/
@EnableConfigurationProperties(value = {MysqlProperties.class})
@MapperScan(value = {"com.ikas.ai.server.module.*.dao"}, sqlSessionFactoryRef = "MysqlSqlSessionFactory")
@Slf4j
@Configuration
public class MysqlConfig {

    @Autowired
    private MysqlProperties mysqlProperties;

    private static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
    private static final String MAPPER_LOCATION = "classpath:mybatis/mysql/mapper/*.xml";
    private static final String VALIDATE_QUERY = "select 1 from dual";
    private static final String TYPE_ALIASES_PACKAGE = "com.ikas.ai.server.module.*.model";

    /**
     * 创建mysql数据源
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "MysqlDataSource")
    public DataSource createMysqlDataSource() throws Exception {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(DRIVER_CLASS_NAME);
        dataSource.setUrl(mysqlProperties.getHost());
        dataSource.setPassword(mysqlProperties.getDbPassword());
        dataSource.setUsername(mysqlProperties.getUserName());
        dataSource.setInitialSize(mysqlProperties.getInitSize());
        dataSource.setMinIdle(mysqlProperties.getMinIdleSize());
        dataSource.setMaxActive(mysqlProperties.getMaxActiveSize());
        dataSource.setMaxWait(mysqlProperties.getMaxWait());
        dataSource.setValidationQuery(VALIDATE_QUERY);
        log.info("初始化mysql数据源成功url:{}", mysqlProperties.getHost());
        return dataSource;
    }

    /**
     * 创建事务管理器（默认使用mysql事务管理器）
     *
     * @param dataSource
     * @return
     */
    @Bean(name = "MysqlTransactionManager")
    @Primary
    public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("MysqlDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 创建session factory
     *
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean(name = "MysqlSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("MysqlDataSource") DataSource dataSource) throws Exception {
        final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage(TYPE_ALIASES_PACKAGE);
        sessionFactory.setConfiguration(createConfiguration());
        sessionFactory.setPlugins(mybatisPlusInterceptor());
        org.springframework.core.io.Resource[] resources = new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION);
        sessionFactory.setMapperLocations(resources);
        return sessionFactory.getObject();
    }

    /**
     * 创建 mybatis配置
     *
     * @return
     */
    private MybatisConfiguration createConfiguration() {
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        mybatisConfiguration.setMapUnderscoreToCamelCase(true);
        mybatisConfiguration.setCallSettersOnNulls(true);

        GlobalConfig globalConfig = new GlobalConfig();
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        dbConfig.setIdType(IdType.AUTO);
        globalConfig.setDbConfig(dbConfig);
        //添加自定义的字段自动填充处理类
        globalConfig.setMetaObjectHandler(new MybatisObjectHandler());
        GlobalConfigUtils.setGlobalConfig(mybatisConfiguration, globalConfig);

        return mybatisConfiguration;
    }

    @Bean("MysqlSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("MysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    private MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 开启乐观锁
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
